<chapter xml:id="str2num.h">
<title><tt>__vic/str2num.h</tt></title>


<chapter xml:id="decimal_to_number">
<title><tt>decimal_to_number()</tt></title>

<code-block lang="C++"><![CDATA[
#if __cpp_lib_string_view // since C++17

void decimal_to_number(std::string_view s, long long &res);
void decimal_to_number(std::string_view s, long &res);
void decimal_to_number(std::string_view s, int &res);
void decimal_to_number(std::string_view s, short &res);
void decimal_to_number(std::string_view s, signed char &res);

void decimal_to_number(std::string_view s, unsigned long long &res);
void decimal_to_number(std::string_view s, unsigned long &res);
void decimal_to_number(std::string_view s, unsigned &res);
void decimal_to_number(std::string_view s, unsigned short &res);
void decimal_to_number(std::string_view s, unsigned char &res);

template<class Integer>
[[nodiscard]] Integer decimal_to_number(std::string_view s);

#else // until C++17

void decimal_to_number(const std::string &s, long long &res);
void decimal_to_number(const std::string &s, long &res);
void decimal_to_number(const std::string &s, int &res);
void decimal_to_number(const std::string &s, short &res);
void decimal_to_number(const std::string &s, signed char &res);

void decimal_to_number(const std::string &s, unsigned long long &res);
void decimal_to_number(const std::string &s, unsigned long &res);
void decimal_to_number(const std::string &s, unsigned &res);
void decimal_to_number(const std::string &s, unsigned short &res);
void decimal_to_number(const std::string &s, unsigned char &res);

void decimal_to_number(const char *s, long long &res);
void decimal_to_number(const char *s, long &res);
void decimal_to_number(const char *s, int &res);
void decimal_to_number(const char *s, short &res);
void decimal_to_number(const char *s, signed char &res);

void decimal_to_number(const char *s, unsigned long long &res);
void decimal_to_number(const char *s, unsigned long &res);
void decimal_to_number(const char *s, unsigned &res);
void decimal_to_number(const char *s, unsigned short &res);
void decimal_to_number(const char *s, unsigned char &res);

template<class Integer>
[[nodiscard]] Integer decimal_to_number(const std::string &s);

template<class Integer>
[[nodiscard]] Integer decimal_to_number(const char *s);

#endif
]]></code-block>

<p>The set of functions converts a string, that represents an integer in
decimal notation, to one of the standard C++ integer types. The string can be
a C-string as well as <tt>std::string</tt>.</p>

<p>As opposed to the standard converters, like <tt>std::strtol()</tt>, strict
validation of the format of the whole string and value range is performed. In
particular leading spaces and non-digit characters at the end are not allowed.
For unsigned types minus (<tt>'-'</tt>) is disallowed, which is happily accepted
by <tt>std::strtoul()</tt> by unknown reason.</p>

<p>In case of errors the following exceptions are thrown:</p>
<list style="bulleted">
    <item><tt>std::invalid_argument</tt> - the string is not a correct decimal
        integer;</item>
    <item><tt>std::range_error</tt> - the string is probably correct but the
        result cannot be represented by the used type (integer overflow).</item>
</list>

<p>There are two kinds of the function prototypes:</p>
<list style="numbered">
    <item>The result is returned via additional output parameter and</item>
    <item>The result is returned using the natural way, the type is specified
        using the template parameter.</item>
</list>

</chapter>


<chapter xml:id="decimal_to_number_range">
<title><tt>decimal_to_number_range()</tt></title>

<code-block lang="C++"><![CDATA[
template<class T, class InputIterator>
void decimal_to_number_range(InputIterator begin, InputIterator end, T &res);

template<class T, class InputIterator>
[[nodiscard]] T decimal_to_number_range(InputIterator begin, InputIterator end);
]]></code-block>

<p>The functions are complete analogs of <tt>decimal_to_number()</tt> except
they work with generic ranges of characters instead of strings.</p>

</chapter>


<chapter xml:id="parse_decimal">
<title><tt>parse_decimal()</tt></title>

<code-block lang="C++"><![CDATA[
#if __cpp_lib_string_view // since C++17

template<class T>
[[nodiscard]] number_parse_result<T> parse_decimal(std::string_view s);

#else // until C++17

template<class T>
[[nodiscard]] number_parse_result<T> parse_decimal(const std::string &s);
template<class T>
[[nodiscard]] number_parse_result<T> parse_decimal(const char *s);

#endif

template<class T, class InputIterator>
[[nodiscard]]
number_parse_result<T> parse_decimal(InputIterator begin, InputIterator end);
]]></code-block>

<p>A counterpart of <tt>decimal_to_number()</tt> functions but doesn't throw
exceptions. The returned object is boolean-testable and indicates the success
of the operation. Also it contains the resulting number in case of success, or
an error code otherwise. See <xref to="number_parse_result"/> for more
information.</p>

<section><title>Example</title>
<code-block lang="C++"><![CDATA[
if(auto res = __vic::parse_decimal<int>("123"))
{
    int num = res.value();
    // Use num
}
]]></code-block>
</section>

</chapter>


<chapter xml:id="decimal_parser">
<title><tt>decimal_parser</tt></title>

<code-block lang="C++"><![CDATA[
template<class T>
class decimal_parser
{
    using status = number_parse_status; // for brevity only
public:
    template<class InputIterator>
    [[nodiscard]] status parse(InputIterator begin, InputIterator end);
#if __cpp_lib_string_view // since C++17
    [[nodiscard]] status parse(std::string_view str);
#else // until C++17
    [[nodiscard]] status parse(const std::string &str);
    [[nodiscard]] status parse(const char *str);
#endif
    [[nodiscard]] T result() const;
};
]]></code-block>

<p>A counterpart of <tt>decimal_to_number()</tt> functions but doesn't throw
exceptions, <xref to="number_parse_status"/> codes are returned instead by
<tt>parse()</tt>.</p>

<section><title>Status codes</title>
<synopsis>
<prototype>number_parse_status::ok</prototype>
<p>Success, the result can be obtained using <tt>result()</tt> function.</p>
</synopsis>
<synopsis>
<prototype>number_parse_status::invalid_number</prototype>
<p>The string is not a correct decimal integer.</p>
</synopsis>
<synopsis>
<prototype>number_parse_status::unrepresentable</prototype>
<p>The string is probably correct but the result cannot be represented by the
used type (integer overflow).</p>
</synopsis>
</section>

<section><title>Class members</title>

<synopsis>
<prototype>template&lt;class InputIterator>
[[nodiscard]] status parse(InputIterator begin, InputIterator end)</prototype>
<prototype>[[nodiscard]] status parse(std::string_view str) <badge>C++17</badge></prototype>
<prototype>[[nodiscard]] status parse(const std::string &amp;str) <badge>until C++17</badge></prototype>
<prototype>[[nodiscard]] status parse(const char *str) <badge>until C++17</badge></prototype>
<p>Converts a range of characters or a string to a number.</p>
<postcondition>The result of conversion can be obtained by <tt>result()</tt>
call if <tt>number_parse_status::ok</tt> is returned.
</postcondition>
</synopsis>

<synopsis>
<prototype>[[nodiscard]] T result() const</prototype>
<p>Returns the result of conversion produced by the the last <tt>parse()</tt>
call.</p>
<precondition>The last <tt>parse()</tt> call returned
<tt>number_parse_status::ok</tt>.</precondition>
</synopsis>

</section>

<section><title>Example</title>
<code-block lang="C++"><![CDATA[
template<class T>
bool to_number(const std::string &s, T &result) noexcept
{
    __vic::decimal_parser<T> p;
    if(p.parse(s) != __vic::number_parse_status::ok) return false;
    result = p.result();
    returt true; // 'result' contains the result of conversion
}
]]></code-block>
</section>

</chapter>


<chapter xml:id="number_parse_status">
<title><tt>number_parse_status</tt></title>

<code-block lang="C++"><![CDATA[
enum class number_parse_status : unsigned char
{
    ok,
    invalid_number,
    unrepresentable
};
using number_parse_status_t = number_parse_status; // for C++98
]]></code-block>

<p>Number parsing outcome status codes.</p>

<section><title>Types</title>

<synopsis>
<prototype>typename number_parse_status_t</prototype>
<p>Use this as a name of type if your code has to be C++98-compatible.</p>
</synopsis>

</section>

</chapter>


<chapter xml:id="number_parse_result">
<title><tt>number_parse_result</tt></title>

<code-block lang="C++"><![CDATA[
template<class T>
class number_parse_result
{
public:
    typedef T value_type;

    number_parse_result(number_parse_status_t s);
    explicit number_parse_result(T n);

    number_parse_status_t status() const;
    explicit operator bool() const;
    bool has_value() const;

    T value() const;
};
]]></code-block>

<p><tt>number_parse_status</tt> + the resulting value in case of success.</p>

<section><title>Class members</title>

<synopsis>
<prototype>number_parse_result(number_parse_status_t s)</prototype>
<precondition><tt>s != number_parse_status::ok</tt></precondition>
<postcondition><tt>status() == s</tt></postcondition>
</synopsis>

<synopsis>
<prototype>explicit number_parse_result(T n)</prototype>
<postcondition><tt>has_value() &amp;&amp; value() == n</tt></postcondition>
</synopsis>

<synopsis>
<prototype>number_parse_status_t status() const</prototype>
<p>A status of the number parsing operation.</p>
</synopsis>

<synopsis>
<prototype>bool has_value() const</prototype>
<prototype>explicit operator bool() const</prototype>
<p>Returns <tt>status() == number_parse_status::ok</tt>.</p>
</synopsis>

<synopsis>
<prototype>T value() const</prototype>
<p>The resulting number.</p>
<precondition><tt>has_value() == true</tt></precondition>
</synopsis>

</section>

</chapter>


</chapter>
